import requests
import json

from sqlalchemy.orm import sessionmaker,declarative_base
from sqlalchemy import Integer,String,Column,Float,create_engine


from langchain_core.tools import tool
from langchain_openai import ChatOpenAI

from langgraph.prebuilt import create_react_agent
from langgraph.graph.message import add_messages
from langgraph.graph import END

from typing import Union,Optional,Annotated
from pydantic import BaseModel,Field
from typing_extensions import TypedDict

def get_weather(loc):
    """
    Function to query current weather.
    :param loc: Required parameter, of type string, representing the specific city name for the weather query. \
    Note that for cities in China, the corresponding English city name should be used. For example, to query the weather for Beijing, \
    the loc parameter should be input as 'Beijing'.
    :return: The result of the OpenWeather API query for current weather, with the specific URL request address being: https://api.openweathermap.org/data/2.5/weather. \
    The return type is a JSON-formatted object after parsing, represented as a string, containing all important weather information.
    """
    # Step 1.构建请求
    url = "https://api.openweathermap.org/data/2.5/weather"

    # Step 2.设置查询参数
    params = {
        "q": loc,
        "appid": "5c939a7cc59eb8696f4cd77bf75c5a9a",  # 输入API key
        "units": "metric",  # 使用摄氏度而不是华氏度
        "lang": "zh_cn"  # 输出语言为简体中文
    }

    # Step 3.发送GET请求
    response = requests.get(url, params=params)

    # Step 4.解析响应
    data = response.json()
    return json.dumps(data)


# res = get_weather("chongqing")
# print(res)

# 创建基类

Base = declarative_base()

# 定义 WeatherInfo 模型
class Weather(Base):
    __tablename__= 'weather'
    city_id = Column(Integer,primary_key=True,autoincrement=True)# 城市ID
    city_name = Column(String(50)) # 城市名称
    main_weather = Column(String(50)) # 主要天气状况
    description = Column(String(100)) # 描述
    temperature = Column(Float) # 温度
    feels_like = Column(Float) # 体感温度
    temp_min = Column(Float) # 最低温度
    temp_max = Column(Float) # 最高温度

# 数据库连接 URI，这里要替换成自己的Mysql 连接信息，以下是各个字段的对应解释：
# root：MySQL 数据库的用户名。
# 123456：MySQL 数据库的密码。
# localhost：MySQL 服务器的 IP 地址。
# langgraph：要连接的数据库的名称。
# charset=utf8mb4：设置数据库的字符集为 utf8mb4，支持更广泛的 Unicode 字符
DATABASE_URI = "mysql+pymysql://root:1qaz2wsx@localhost:3306/langgraph?charset=utf8mb4"
engine = create_engine(DATABASE_URI)

# 如果表不存在，则创建表
Base.metadata.create_all(engine)

# 创建会话
Session = sessionmaker(bind=engine)

class WeatherLoc(BaseModel):
    location: str = Field(description="The location name of the city")

class WeatherInfo(BaseModel):
    city_id: int = Field(...,description="The name of the city")
    city_name: str = Field(...,description="The name of the city")
    main_weather: str = Field(...,description="The main weather condition")
    description: str = Field(...,description="A detailed description of the weather")
    temperature: float=Field(...,description="Current temperature in Celsius")
    feels_like: float=Field(...,description="Feels-like temperature in Celsius")
    temp_min: float=Field(...,description="Minimum temperature in Celsius")
    temp_max: float=Field(...,description="Maximum temperature in Celsius")

@tool(args_schema=WeatherLoc)
def get_weather(location):
    """
        Function to query current weather.
        :param loc: Required parameter, of type string, representing the specific city name for the weather query. \
        Note that for cities in China, the corresponding English city name should be used. For example, to query the weather for Beijing, \
        the loc parameter should be input as 'Beijing'.
        :return: The result of the OpenWeather API query for current weather, with the specific URL request address being: https://api.openweathermap.org/data/2.5/weather. \
        The return type is a JSON-formatted object after parsing, represented as a string, containing all important weather information.
        """
    # Step 1.构建请求
    url = "https://api.openweathermap.org/data/2.5/weather"

    # Step 2.设置查询参数
    params = {
        "q": location,
        "appid": "5c939a7cc59eb8696f4cd77bf75c5a9a",  # 输入API key
        "units": "metric",  # 使用摄氏度而不是华氏度
        "lang": "zh_cn"  # 输出语言为简体中文
    }

    # Step 3.发送GET请求
    response = requests.get(url,params=params)

    # Step 4.解析响应
    data = response.json()
    return json.dumps(data)


@tool(args_schema=WeatherInfo)
def insert_weather_to_db(city_id,city_name,main_weather,description,temperature,feels_like,temp_min,temp_max):
    """Insert weather information into the database."""
    session = Session()# 确保为每次操作创建新的会话
    try:
        # 创建天气实例
        weather = Weather(
            city_id=city_id,
            city_name = city_name,
            main_weather=main_weather,
            description=description,
            temperature=temperature,
            feels_like=feels_like,
            temp_min=temp_min,
            temp_max=temp_max
        )
        # 使用 merge 方法来插入或更新（如果已有记录则更新）
        session.merge(weather)
        # 提交事务
        session.commit()
        return {"messages":[f"天气数据已成功存储至Mysql数据库。"]}
    except Exception as e:
        session.rollback()# 出错时回滚
        return {"messages":[f"数据存储失败，错误原因：{e}"]}
    finally:
        session.close()

class QueryWeatherSchema(BaseModel):
    """Schema for querying weather information by city name."""
    city_name:str=Field(...,description="The name of the city to query weather information")

@tool(args_schema=QueryWeatherSchema)
def query_weather_from_db(city_name):
    """Query weather information from the database by city name."""
    session = Session()
    try:
        # 查询天气数据
        weather_data = session.query(Weather).filter(Weather.city_name == city_name).first()
        if weather_data:
            return {
                "city_id":weather_data.city_id,
                "city_name":weather_data.city_name,
                "main_weather": weather_data.main_weather,
                "description": weather_data.description,
                "temperature": weather_data.temperature,
                "feels_like": weather_data.feels_like,
                "temp_min": weather_data.temp_min,
                "temp_max": weather_data.temp_max
            }
        else:
            return {"messages": [f"未找到城市 '{city_name}' 的天气信息。"]}
    except Exception as e:
        return {"messages": [f"查询失败，错误原因：{e}"]}
    finally:
        session.close()

class SearchQuery(BaseModel):
    query: str = Field(description="Questions for networking queries")


@tool(args_schema=SearchQuery)
def fetch_real_time_info(query):
    """Get real-time Internet information"""
    url = "https://google.serper.dev/search"
    payload = json.dumps({
        "q": query,
        "num": 1,
    })
    headers = {
        'X-API-KEY': '22a84d67009121271e4a5eb21d809e11d3bc8d45',
        'Content-Type': 'application/json'
    }
    response = requests.post(url,headers=headers,data=payload)

    data = json.loads(response.text)# 将返回的JSON字符串转换为字典
    if 'organic' in data:
        return json.dumps(data['organic'],  ensure_ascii=False)  # 返回'organic'部分的JSON字符串
    else:
        return json.dumps({"error": "No organic results found"},  ensure_ascii=False)  # 如果没有'organic'键，返回错误信息

tools = [fetch_real_time_info,query_weather_from_db,insert_weather_to_db,get_weather]


api_key = "sk-6S0PtpNia71gjcfwSsDPsJ9mGqsVPr2XRQzAx1dHbJS7RW4t"
api_base="https://chatapi.littlewheat.com/v1"

llm = ChatOpenAI(model="gpt-4o",api_key=api_key,base_url=api_base)

graph = create_react_agent(llm,tools=tools)

# class State(TypedDict):
#     messages:Annotated[list,add_messages]
#
# def should_continue(state:State):
#     last_messages = state["messages"][-1]
#     # 如果不是工具调用，则结束
#     if not last_messages.tool_calls:
#         return END
#     # 如果是的话，则进入工具库中选择函数执行
#     else:
#         return "tools"

# final_response = graph.invoke({"messages":["你好，请你介绍一下你自己"]})
# final_response = graph.invoke({"messages":["北京今天的天气怎么样？"]})
final_response = graph.invoke({"messages":["你知道关于小米的销售情况吗？请用中文回复我"]})
print(final_response)
